// eslint-disable-next-line prettier/prettier
import Taro from '@tarojs/taro'

// eslint-disable-next-line prettier/prettier
import { eventEmitter, GLOBAL_EVENT_NAME, GlobalApi, notEmpty, storage, STORAGE_KEYS } from '@/common'
import { TIME } from '@/common/constants'
import { exec } from '@/common/request/request'
import { RequestStore, UserInfoStore } from '@/store'

import { singleInstancePromise } from '../utils/singleInstancePromise'
import { promisify, showToast } from '../utils/tools'

// 登录/注册
export const loginService = async (force = false) => {
  try {
    const user = UserInfoStore.userInfo
    if (notEmpty(user) && !force) return
    const loginPromisify = promisify(Taro.login)
    const { code } = (await loginPromisify()) as { code: string }
    console.log('%c 🥝 code', 'font-size:13px; background:#70cf95; color:#b4ffd9;', code)
    const data = await GlobalApi.login({ code })
    const { userInfo, token } = data
    UserInfoStore.setUserInfo(userInfo)
    storage.setStorage(STORAGE_KEYS.TOKEN, token)
    return userInfo
  } catch (error) {
    console.log('%c 🥝 error 🥝-32', 'font-size:13px; background:#1fc7ae; color:#63fff2;', error)
  }
}

// 单例静默登录/注册
export const silentLogin = singleInstancePromise(loginService)

// 获取新的 token
export const refreshNewTokenRequest = async (response: any) => {
  try {
    // 在 token 有效时间内不再刷新，防止重复请求
    storage.setStorageExTimeSync(STORAGE_KEYS.LAST_TRY_TOKEN_TIME, new Date(), TIME.TOKEN_SAFETY_TIME)

    // 强制重新登录
    const force = true
    const data = await silentLogin(force)
    if (notEmpty(data)) {
      // 登录后，将请求队列中的请求重新发起
      RequestStore.refreshTokenSuccess()
      eventEmitter.emit(GLOBAL_EVENT_NAME.REQUEST_QUERY, response)
      return
    }
    return showToast('服务异常请重新加载小程序')
  } catch (error) {
    console.log('%c🥝 error 🥝-27', 'font-size:13px; background:#4511ee; color:#8955ff;', error)
    showToast('服务异常请重新加载小程序')
  }
}

// 刷新 token 逻辑
export const refreshTokenService = response => {
  const lastTryTokenTime = storage.getStorageExTimeSync(STORAGE_KEYS.LAST_TRY_TOKEN_TIME)
  // token 有效期内不再刷新
  if (lastTryTokenTime) {
    const token = storage.getStorageSync(STORAGE_KEYS.TOKEN)
    response.header['token'] = token
    exec(response)
    return
  }

  const { isRefreshToken } = RequestStore
  // 如果没有正在刷新 token，就去刷新
  if (!isRefreshToken) {
    RequestStore.refreshTokenPending()
    refreshNewTokenRequest(response)
  }

  // 将请求放入请求队列，token 刷新后执行队列的请求任务
  return new Promise(resolve => {
    eventEmitter.on(GLOBAL_EVENT_NAME.REQUEST_QUERY, requestConfig => {
      const token = storage.getStorageSync(STORAGE_KEYS.TOKEN)
      requestConfig.header['token'] = token
      resolve(exec(requestConfig))
    })
  })
}
